package me.zhengjie.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import me.zhengjie.domain.FlowConfig;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.mapper.FlowConfigToolMapper;
import me.zhengjie.service.FlowConfigToolService;
import me.zhengjie.service.OrganizerService;
import org.flowable.bpmn.model.*;
import org.flowable.bpmn.model.Process;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 18485
 */
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "organizer")
public class OrganizerServiceImpl extends ServiceImpl<FlowConfigToolMapper,FlowConfig> implements OrganizerService {

    @Autowired
    FlowConfigToolService flowConfigToolService;
    @Autowired
    RepositoryService repositoryService;
    @Autowired
    ProcessEngine processEngine;

    @Override
    public void deploymentRun(Map<String, String> map){
        try {
            String jsonData = map.get("xml");
            String name = map.get("name");
            String key = map.get("key");
            FlowConfig flowConfig1 = infoFlow(map);
            if (flowConfig1 != null && name.equals(flowConfig1.getFlowName())){
                throw new BadRequestException("流程已存在");
            }
            BpmnModel xml = jsonToBpmn(jsonData);
            Deployment deployment = repositoryService.createDeployment()
                    .addBpmnModel(name+".bpmn", xml)
                    .name(name)
                    .deploy();
            ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                    .deploymentId(deployment.getId())
                    .singleResult();
            FlowConfig flowConfig = new FlowConfig();
            flowConfig.setFlowName(name);
            flowConfig.setFlowId(processDefinition.getId());
            flowConfig.setFlowKey(key);
            flowConfig.setOrginalData(jsonData);
            flowConfig.setStatus(1);
            save(flowConfig);
        } catch (Exception e) {
            throw new BadRequestException("deploymentRun:"+e);
        }
    }

    public FlowConfig infoFlow(Map<String, String> map) {
        // String id = map.get("id");
        String name = map.get("name");
        FlowConfig flowConfig = baseMapper.selectOne(new QueryWrapper<FlowConfig>().eq("flow_name", name));
        // 流程查询
//            RepositoryService repositoryService = processEngine.getRepositoryService();
//            InputStream resourceAsStream = repositoryService.getResourceAsStream(flowConfig.getFlowId(), name + ".bpmn");
//
//            // Java流转String
//            String resultXml = new BufferedReader(new InputStreamReader(resourceAsStream, "utf-8"))
//                    .lines().collect(Collectors.joining(System.lineSeparator()));
            return flowConfig;
    }

    @Override
    public void updateFlow(Map<String, String> map) {
        try {
            String jsonData = map.get("xml");
            String name = map.get("name");
            FlowConfig flowConfig = baseMapper.selectOne(new QueryWrapper<FlowConfig>().eq("flow_name", name));
            BpmnModel xml = jsonToBpmn(jsonData);
            repositoryService.createDeployment().addBpmnModel(name+".bpmn", xml).name(name).deploy();
            flowConfig.setOrginalData(jsonData);
            saveOrUpdate(flowConfig);
        }catch (Exception e){
            throw new BadRequestException("updateFlow:"+e);
        }
    }

    BpmnModel jsonToBpmn(String result) throws Exception {
        // 解析 JSON 数据
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode rootNode = objectMapper.readTree(result);
        Map<String, FlowNode> nodeMap = new HashMap<>();
        BpmnModel bpmnModel = new BpmnModel();
        Process process = new Process();
        bpmnModel.addProcess(process);
        process.setId("myProcess");
        JsonNode jsonNodes = rootNode.get("nodes");
        JsonNode jsonEdges = rootNode.get("edges");
// 解析 nodes
        for (JsonNode node : jsonNodes) {
            String nodeId = node.get("id").asText();
            String nodeName = node.get("properties").get("name").asText();
            String nodeType = node.get("type").asText();

            if ("event-node".equals(nodeType)) {
                StartEvent startEvent = new StartEvent();
                startEvent.setId(nodeId);
                startEvent.setName(nodeName);
                process.addFlowElement(startEvent);
            } else if ("common-node".equals(nodeType)) {
                String componentName = node.get("properties").get("componentName").asText();
                if ("dataSource".equals(componentName)) {
                    ServiceTask serviceTask = new ServiceTask();
                    serviceTask.setId(nodeId);
                    serviceTask.setName(nodeName);
                    serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
                    serviceTask.setImplementation("${dataSourceService.execute}");
                    process.addFlowElement(serviceTask);
                } else if ("pageJump".equals(componentName)) {
                    ServiceTask serviceTask = new ServiceTask();
                    serviceTask.setId(nodeId);
                    serviceTask.setName(nodeName);
                    serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
                    serviceTask.setImplementation("${pageJumpService.execute}");
                    process.addFlowElement(serviceTask);
                } else if ("dataConvert".equals(componentName)) {
                    ServiceTask serviceTask = new ServiceTask();
                    serviceTask.setId(nodeId);
                    serviceTask.setName(nodeName);
                    serviceTask.setImplementationType(ImplementationType.IMPLEMENTATION_TYPE_EXPRESSION);
                    serviceTask.setImplementation("${dataConvertService.execute}");
                    process.addFlowElement(serviceTask);
                }
            }
        }
// 解析 edges
        for (JsonNode edge : jsonEdges) {
            String sourceRef = edge.get("sourceNodeId").asText();
            String targetRef = edge.get("targetNodeId").asText();

            SequenceFlow flow = new SequenceFlow();
            flow.setId(edge.get("id").asText());
            flow.setSourceRef(sourceRef);
            flow.setTargetRef(targetRef);
            process.addFlowElement(flow);
        }

        // 部署流程定义
        return bpmnModel;
    }


}
